
// questo è un commento a linea singola in puro stile C++

/* questo è il vecchio commento multilinea
in stile C */


/* la programamzione ad oggetti supporta */
// l'incapsulamento
// il polimorfismo
// l'ereditarietà 

// esempio di incapsulamento: dati e funzioni in un oggetto


// un oggetto è una istanza di una classe

// include la necessaria intestazione <iostream>
#include <iostream>

// l'istruzione using informa il compilatore che intende utilizzare il namespace standard
using namespace std; 
// i namespace creano delle regioni di dichiarazione
// nel namespace standard viene dichiarata l'intera libreria standard del C++

#define SIZE 100

// Creazione della classe pila
// una classe può contenere parti private e parti pubbliche
// in generale tutti gli oggetti dichiarati all'interno di una classe sono privati
class pila {
private: //private è pleonastico (si può omettere)
  int PILA[SIZE];
  int puntatore_pila;
// le variabili PILA e puntatore_pila si chiamano variabili membro e sono private
// questo significa che non sono visibili da nessun'altra funzione che non sia
// un membro della classe
public:
// tutte le variabili e le funzioni definite dopo public sono pubbliche ovvero
// possono essere utilizzate da tutte le altre funzioni del programma
// limitare le variabili pubbliche
  void inizializza();
  void push(int); 
  int  pop();
  void indirizzo() {printf ("%d \n%d\n", &puntatore_pila, &PILA[99]);}

// inizializza, push e pop sono chiamate funzioni membro poichè membri della classe pila
// solo le funzioni membro possono accedere alle variabili private
// PILA e puntatore_pila
// all'interno della dichiarazione di pila le funzioni membro sono identificate dai prototipi
// in C++ tutte le funzioni devono avere un prototipo 
};

// Inizializza la pila
// Bisogna dire al compilatore la classe a cui appartiene la funzione
// la funzione visualizza è funzione mebro della classe pila
// l'operatore "::" chiamato operatore di risoluzione del campo di azione
// specifica che inizializza è nel campo di azione di pila
void pila::inizializza()
{
  puntatore_pila= 0;
}

// Inserimento di un intero nella pila
void pila::push(int i)
{
  if(puntatore_pila==SIZE) {
    cout << "Pila piena\n";
    //return;
  }
  PILA[puntatore_pila]=i;
  puntatore_pila++;
}

// Estrazione di un intero dalla pila
int pila::pop()
{
  if(puntatore_pila == 0) {
    cout << "Pila vuota\n";
    return 0;
  }
  puntatore_pila--;
  return PILA[puntatore_pila];
}

int main()
{
  pila pila1, pila2 ;
  //cout << sizeof(pila2) << endl;
// creazione di due oggetti della classe pila
// il nome della classe diviene uno specificatore di tipo
// Ricordate struct?
// pila1 e pila2 sono oggetti ovvero istanze della classe pila
// la classe è un'astrazione logica
// gli oggetti sono reali ovvero esistono in memoria

pila1.indirizzo();
  pila1.inizializza();
// quando si deve fare riferimento ad un membro di una classe (dato o funzione che sia)
// da una parte di codice che non si trova all'interno della classe stessa
// tale operazione deve essere eseguita sempre in congiunzione con un oggetto di tale classe
// per fare questo si usa l'operatore "." chiamato operatore di selezione
  
// pila1.puntatore_pila=0; non consentito nel main perchè puntatore_pila è private
  pila2.inizializza();

  pila1.push(1);
  pila2.push(2);

  pila1.push(3);
  pila2.push(4);
  // cout: canale di outut ovvero console di output
  cout << "speriamo che funzioni, " <<"boh?" << endl <<endl;
  cout << pila1.pop() << endl;
  cout << pila1.pop() << endl;
  cout << pila2.pop() << endl;
  cout << pila2.pop() << "\n";
  printf("\n");


  return 0;
}

/* risultato
speriamo che funzioni, boh?

3
1
4
2

Press any key to continue
*/